package controllers

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"strconv"
	"strings"

	"models"

	"github.com/astaxie/beego"
)

type SheetResponse struct {
	Code    int `json:"code"`
	Message string
	Count   int
	Data    string
}

type MainController struct {
	beego.Controller
}

type TestController struct {
	beego.Controller
}

func (c *MainController) Get() {
	c.Data["Website"] = "beego.me"
	c.Data["Email"] = "astaxie@gmail.com"
	c.TplName = "index.tpl"
}

func (c *TestController) getComputedContent() string {
	var resp string
	computeID := c.GetString("id")
	page, err := strconv.Atoi(c.GetString("page"))
	if err != nil {
		page = 0
	}
	limit, err := strconv.Atoi(c.GetString("limit"))
	if err != nil {
		limit = 0
	}

	cid, err := strconv.ParseInt(computeID, 10, 64)
	if err != nil {
		resp = `{"code":500, "msg":"` + err.Error() + `"}`
		return resp
	}

	count := models.GetComputedArrayConut(cid)
	retArr := models.GetComputedArrayData(cid, page, limit)
	//count = models.GetTestArrayCount()
	//retArr = models.GetTestArrayData()
	bret, err := json.Marshal(retArr)
	if err != nil {
		resp = `{"code":501, "msg":"` + err.Error() + `"}`
		return resp
	}

	resp = `{"code":0, "msg":"", "count":` + strconv.Itoa(count) +
		`,"data":` + string(bret) + "}"

	return resp
}

func (c *TestController) Get() {
	if c.Ctx.Input.URL() == "/test.do" {
		c.TplName = "test.tpl"
	} else if c.Ctx.Input.URL() == "/content.do" {
		resp := c.getComputedContent()
		c.Ctx.WriteString(resp)
	}
}

func (c *TestController) Post() {
	if c.Ctx.Input.URI() == "/command.do" {
		c.handleForCommand()
	} else if c.Ctx.Input.URI() == "/pushFile.do" {
		c.handleForPushFile()
	}
}

func (c *TestController) handleForPushFile() {
	f, h, err := c.GetFile("file")
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	defer f.Close()

	resp, err := c.saveFileAndParse(h.Filename)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	c.Ctx.WriteString(resp)
}

func (c *TestController) saveFileAndParse(fileName string) (string, error) {
	savePath, err := os.Getwd()
	if err != nil {
		return "", err
	}
	savePath += string(os.PathSeparator) + fileName

	err = c.SaveToFile("file", savePath)
	if err != nil {
		return "", err
	}

	exlParser := models.GetExcelParser()
	if exlParser == nil {
		return "", errors.New("alloc excel parse fail")
	}

	err = exlParser.OpenXLSX(savePath)
	if err != nil {
		return "", err
	}

	models.SetSheetRecordFromFile(exlParser, fileName)

	// append fields; save parser handle
	ret := `{"code":0 ,"msg":"upload done", "files":{"file":"` + fileName + `"},` +
		c.getFieldsArrayString(exlParser) + "}"

	return ret, err
}

func (c *TestController) getFieldsArrayString(exlParser *models.ExcelParser) string {
	fieldArrStr := `"fields":[`
	for _, v := range exlParser.FieldsArr {
		fieldArrStr += `"` + v + `"` + ","
	}
	fieldArrStr = strings.TrimRight(fieldArrStr, ",")
	fieldArrStr += "]"

	return fieldArrStr
}

func (c *TestController) responseClient(ret models.SheetData) {
	bresp, err := json.Marshal(ret)
	if err != nil {
		c.Ctx.WriteString(err.Error())
	} else {
		c.Ctx.WriteString(string(bresp))
	}
}

func (c *TestController) uniqCompute() error {
	fileName := c.GetString("name")
	fields := c.GetString("field")

	fieldArray := strings.Split(fields, ",")
	var retArr []interface{}
	var err error
	var computeID int64

	for _, v := range fieldArray {
		retArr, err = models.UniqSheetOneCol(fileName, v, retArr)
		if err != nil {
			return err
		}
	}

	if len(retArr) > 0 {
		computeID = models.SetComputedResult(fileName, retArr, "")
	}

	ret := models.GetResponseData(computeID)
	c.responseClient(ret)

	return nil
}

func (c *TestController) intersectionCompute() error {
	fs := c.GetString("field")
	computeID, err := models.IntersectionCompute(fs)
	if err != nil {
		return err
	}

	ret := models.GetResponseData(computeID)
	c.responseClient(ret)

	return nil
}

func (c *TestController) locationCompute() error {
	var retArr []interface{}
	var err error
	var computeID int64
	fileName := c.GetString("name")
	fields := c.GetString("field")
	fieldArray := strings.Split(fields, ",")

	for _, v := range fieldArray {
		retArr, err = models.LocationCompute(fileName, v, retArr)
		if err != nil {
			return err
		}
	}

	if len(retArr) > 0 {
		computeID = models.SetComputedResult(fileName, retArr, "")
	}

	ret := models.GetResponseData(computeID)
	c.responseClient(ret)

	return err
}

func (c *TestController) locationSimple() error {
	number := c.GetString("number")
	locate, err := models.GetOneLocation(number)
	if err != nil {
		return err
	}

	retStr := `{"Result":"OK", "number":"` + number + `", "location":"` + locate + `"}`
	c.Ctx.WriteString(retStr)
	return err
}

func (c *TestController) handleForCommand() {
	cmd := c.GetString("cmd")
	var ret models.SheetData
	var err error

	if cmd == "uniq" {
		err = c.uniqCompute()
	} else if cmd == "intersection" {
		err = c.intersectionCompute()
	} else if cmd == "location" {
		err = c.locationCompute()
	} else if cmd == "simpleLocation" {
		err = c.locationSimple()
	}

	if err != nil {
		ret.Result = err.Error()
		c.responseClient(ret)
	}
}
